package com.jxl.advice;

import com.alibaba.fastjson.JSON;
import com.jxl.annotation.Role;
import com.jxl.pojo.User;
import com.jxl.utils.WebUtils;
import com.jxl.web.WebResult;
import com.jxl.web.constant.Constant;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * AOP实现权限管理
 * @author 江雪林
 * @create 2021-03-20
 */
@Aspect
@Component
public class AuthenticateAdvice {
    private static final Logger log = Logger.getLogger(AuthenticateAdvice.class);

    /**
     * 以权限注解标注的方法为切入点
     */
    @Pointcut("@annotation(com.jxl.annotation.Role)")
    private void poincut(){}

    /**
     * 使用 环绕通知执行 权限认证
     * @param pjp
     * @return
     */
    @Around("poincut()")
    public Object around(ProceedingJoinPoint pjp) throws IOException {
        Object object = null;
        //获取切入点的执行方法对象
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();
        //获取方法上的权限注解
        Role aRole = method.getAnnotation(Role.class);
        //获取权限
        String[] roles = aRole.value();
        log.info("-> 调用 "+pjp.getTarget()+" 的 "+
                pjp.getSignature().getName()+" 方法。方法入参："+
                Arrays.toString(pjp.getArgs())+"。进行权限认证 <-");
        //检查权限认证
        if(this.valid(roles)==false){
            log.info("->  调用 "+pjp.getTarget()+" 的 "+pjp.getSignature().getName()+" 方法。\n权限认证失败 unsuccessful <-");
            //权限认证失败，操作失败
            return null;
        }
        try {
            log.info("->  调用 "+pjp.getTarget()+" 的 "+pjp.getSignature().getName()+" 方法。\n权限认证成功 successful<-");
            //程序放行
            object = pjp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return object;
    }

    /**
     * 权限验证
     * @param roles 权限
     * @return
     */
    private boolean valid(String[] roles) throws IOException {
        //权限标识
        boolean flag = false;
        //获取request属性
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //获取请求
        HttpServletRequest request = attributes.getRequest();
        //获取session
        HttpSession session = request.getSession();
        //获取当前登录用户
        User user = (User) session.getAttribute("user");
        //获取用户权限
        String urole = user.getRole();
        if(urole != null){
            for(String role:roles){
                //判断用户权限
                if(urole.equals(role)){
                    flag = true;
                    break;
                }
            }
        }
        //如果没有用户权限，返回处理结果
        if(flag==false){
            //处理结果
            HttpServletResponse response = attributes.getResponse();
            response.setContentType("text/html;chatset=utf-8");
            WebResult result = new WebResult(Constant.NO_POWER, Constant.VALID_POWER_UNSUCCESS);
            result.put(false);
            WebUtils.response(response,result);
        }
        return flag;
    }
}
